Skip to content

fix(annotate_types): coerce bigquery date function arg types [CLAUDE]#7790

Merged
georgesittas merged 4 commits into
tobymao:mainfrom
etonlels:fix-bq-date-func-string-literal-annotation
Jun 24, 2026
Merged

fix(annotate_types): coerce bigquery date function arg types [CLAUDE]#7790
georgesittas merged 4 commits into
tobymao:mainfrom
etonlels:fix-bq-date-func-string-literal-annotation

Conversation

@etonlels

Copy link
Copy Markdown
Contributor

In BigQuery these functions return the type of their first argument. They were annotated via _annotate_by_args("this") (DATE_ADD, DATE_TRUNC, DATETIME_TRUNC, TIMESTAMP_TRUNC), which copies the first arg's type verbatim. For a date/datetime string-literal first arg that type is the literal's VARCHAR, so e.g. DATE_ADD('2020-01-01', INTERVAL 1 DAY) was annotated as VARCHAR instead of DATE.

DATE_SUB was separately annotated via the base _annotate_timeunit, which handled the string-literal case but mis-annotated a TIMESTAMP first arg as DATETIME (e.g. DATE_SUB(TIMESTAMP '...', INTERVAL 1 HOUR) -> DATETIME instead of TIMESTAMP).

Route all five through a new bigquery _annotate_date_func: a typed first arg keeps its exact type (via _annotate_by_args), and a string-literal first arg is coerced to the function's own temporal type (DATE_ADD/DATE_SUB/DATE_TRUNC -> DATE, DATETIME_TRUNC -> DATETIME, TIMESTAMP_TRUNC -> TIMESTAMP), matching BigQuery's implicit coercion. Verified against BigQuery for the whole date/time arithmetic family; the change is bigquery-only and does not affect other dialects.

In BigQuery these functions return the type of their first argument. They were
annotated via `_annotate_by_args("this")` (`DATE_ADD`, `DATE_TRUNC`,
`DATETIME_TRUNC`, `TIMESTAMP_TRUNC`), which copies the first arg's type verbatim.
For a date/datetime string-literal first arg that type is the literal's `VARCHAR`,
so e.g. `DATE_ADD('2020-01-01', INTERVAL 1 DAY)` was annotated as `VARCHAR` instead
of `DATE`.

`DATE_SUB` was separately annotated via the base `_annotate_timeunit`, which handled
the string-literal case but mis-annotated a `TIMESTAMP` first arg as `DATETIME` (e.g.
`DATE_SUB(TIMESTAMP '...', INTERVAL 1 HOUR)` -> `DATETIME` instead of `TIMESTAMP`).

Route all five through a new bigquery `_annotate_date_func`: a typed first arg keeps
its exact type (via `_annotate_by_args`), and a string-literal first arg is coerced
to the function's own temporal type (`DATE_ADD`/`DATE_SUB`/`DATE_TRUNC` -> `DATE`,
`DATETIME_TRUNC` -> `DATETIME`, `TIMESTAMP_TRUNC` -> `TIMESTAMP`), matching
BigQuery's implicit coercion. Verified against BigQuery for the whole date/time
arithmetic family; the change is bigquery-only and does not affect other dialects.

Co-Authored-By: OpenCode google-vertex/claude-opus-4-8@default <noreply@opencode.ai>
@georgesittas georgesittas self-assigned this Jun 24, 2026

@georgesittas georgesittas left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, nice catch.

Comment thread sqlglot/typing/bigquery.py
Comment thread sqlglot/typing/bigquery.py Outdated
Comment thread sqlglot/typing/bigquery.py
Comment thread sqlglot/typing/bigquery.py Outdated
@georgesittas georgesittas marked this pull request as ready for review June 24, 2026 10:07
@georgesittas georgesittas merged commit 91a781b into tobymao:main Jun 24, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants